/**
 * grayrabbit Inc.
 * Copyright (c) 2011-2012 All Rights Reserved.
 */
package com.grayrabbit.slacker.gengerate;

import java.io.FileOutputStream;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.grayrabbit.slacker.config.GenerateConfig;
import com.grayrabbit.slacker.constant.ConfigConstant;
import com.grayrabbit.slacker.interfaces.CodeGenerate;
import com.grayrabbit.slacker.utils.TemplateProcessUtils;

/**
 * dao 接口生成工具类
 * 
 * @author liyd
 * @version $Id: DaoGenerate.java, v 0.1 2012-5-15 下午2:34:41 liyd Exp $
 */
public class DaoGenerate extends NormalGenerate implements CodeGenerate {

    /** 
     * @see com.grayrabbit.slacker.interfaces.CodeGenerate#generate(com.grayrabbit.slacker.config.GenerateConfig, java.util.Map)
     */
    public void generate(GenerateConfig generateConfig, Map<String, String> modelMap) {

        //初始化常规数据
        super.normalDataInit(generateConfig);

        modelMap.put("import", "import " + this.ENTITY_QUALIFIED_CLASS_NAME + ";");

        modelMap.put("package", this.PACKAGE);

        modelMap.put("className", this.getClassName(TARGET_QUALIFIED_CLASS_NAME));

        modelMap.put("entityClassName", this.getClassName(ENTITY_QUALIFIED_CLASS_NAME));

        modelMap.put("entityClassInstance",
            TemplateProcessUtils.convertFirstLower(this.getClassName(ENTITY_QUALIFIED_CLASS_NAME)));

        modelMap.put("gmtCreate", this.GMT_CREATE);

        //添加dao在spring文件的声明
        createDaoXml(generateConfig);

    }

    /**
     * 添加dao在spring文件的声明
     * 
     * @param generateConfig
     */
    private void createDaoXml(GenerateConfig generateConfig) {

        String classId = TemplateProcessUtils.convertFirstLower(TemplateProcessUtils
            .getClassName(generateConfig));

        try {
            // 1.得到DOM解析器的工厂实例
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

            // 2.从DOM工厂里获取DOM解析器
            DocumentBuilder db = dbf.newDocumentBuilder();

            String daoXml = ConfigConstant.GENERATE_PROJECT_HOME
                            + generateConfig.getProperties().get("daoXml").getValue();
            // 3.解析XML文档，得到document，即DOM树
            Document doc = db.parse(daoXml);

            //判断该bean是否已经存在
            NodeList nl = doc.getElementsByTagName("bean");
            for (int i = 0; i < nl.getLength(); i++) {
                Node node = nl.item(i);

                NamedNodeMap nodeMap = node.getAttributes();

                String tempClassId = nodeMap.getNamedItem("id").getNodeValue();

                if (classId.equals(tempClassId)) {
                    return;
                }
            }

            // 创建节点
            Element beanElement = doc.createElement("bean");
            beanElement.setAttribute("id", classId);
            beanElement.setAttribute("class", "org.mybatis.spring.mapper.MapperFactoryBean");

            //创建property节点
            Element sqlSessionFactoryElement = doc.createElement("property");
            sqlSessionFactoryElement.setAttribute("name", "sqlSessionFactory");
            sqlSessionFactoryElement.setAttribute("ref", "sqlSessionFactory");

            //创建property节点
            Element mapperInterfaceElement = doc.createElement("property");
            mapperInterfaceElement.setAttribute("name", "mapperInterface");
            mapperInterfaceElement.setAttribute("value", TARGET_QUALIFIED_CLASS_NAME);

            //添加父子关系
            beanElement.appendChild(sqlSessionFactoryElement);
            beanElement.appendChild(mapperInterfaceElement);
            Element beansElement = (Element) doc.getElementsByTagName("beans").item(0);
            beansElement.appendChild(beanElement);

            //保存xml文件
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            transformerFactory.setAttribute("indent-number", Integer.valueOf(2));
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource domSource = new DOMSource(doc);

            //设置编码类型
            transformer.setOutputProperty(OutputKeys.ENCODING, "GB2312");
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            StreamResult result = new StreamResult(new FileOutputStream(daoXml));

            //把DOM树转换为xml文件
            transformer.transform(domSource, result);

        } catch (Exception e) {
            LOG.error("将生成的dao文件添加到spring声明失败", e);
        }
    }

}
